#pragma once

//
// it is necessary to include "U7Objs.h" before including this header file,
// because of the definition of OBJLIST and only U7Objs.h includes U7FileDefs.h
//

#include "TimeQueue.h"

class U7FilesLoader;

//	Wrapping:
#define INCR_CHUNK(x) (((x) + 1)%CHUNKS_PER_MAP_IN_WIDTH)
#define DECR_CHUNK(x) (((x) - 1 + CHUNKS_PER_MAP_IN_WIDTH)%CHUNKS_PER_MAP_IN_WIDTH)

class WorldMap
{
	friend class BasicObject;
	friend class AnimatedTerrainObject;
	friend class IregObject;
	friend class MapChunk;
	friend class Renderer;

	// no replicated
	WorldMap( const WorldMap& x );
	WorldMap& operator = ( const WorldMap& x );

private:
	U7FilesLoader*	u7Files;
	TimeQueue*		tqueue;

	MapChunk*		mapChunks[CHUNKS_PER_MAP_IN_WIDTH][CHUNKS_PER_MAP_IN_HEIGHT]; // [x][[y]
	bool			loadedSuperchunks[SUPERCHUNKS_PER_MAP];

	MapChunk* CreateMapChunk( int chx, int chy );
	void LoadSuperchunk( int iregFileIndex );
	const char* ParseIregFile( int xchkStart, int ychkStart, int size, const char* base, const char* cur, IregObject* container = NULL );
	void LoadNPCs( int iregFileIndex );
	void LoadIbufObject( int offset, int ownerOffset, IregObject* container, PREADIED readied );

	void Patch( BasicObject* obj );

public:
	WorldMap(U7FilesLoader* files, TimeQueue* tq);
	~WorldMap();

	MapChunk* GetMapChunk( int chx, int chy );

	void ReadData( int viewportX, int viewportY, int viewportWidth, int viewportHeight );

	void HitTest( int worldX, int worldY, int zlimit, OBJLIST& hits ) const;
};


inline
MapChunk* WorldMap::GetMapChunk( int chx, int chy )
{
	assert( chx >= 0 && chx < CHUNKS_PER_MAP_IN_WIDTH &&
		chy >= 0 && chy < CHUNKS_PER_MAP_IN_HEIGHT );

	// dynamically allocate map chunk
	MapChunk* mchk = mapChunks[chx][chy];
	return mchk ? mchk : CreateMapChunk(chx,chy);
}


